﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OpGen.Compiler
{
    /// <summary>
    /// Stellt ein Element mit Basisfunktionen dar
    /// </summary>
    public abstract class Element
    {
        private ElementCollection _ChildElements = new ElementCollection();

        /// <summary>
        /// Erstellt eine neue Instanz der BaseElement-Klasse
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="type"></param>
        protected Element(Element parent, ElementTypes type)
        {
            this.ElementType = type;
            this.ParentElement = parent;
            this.Elementname = "";

            GetNamespaceElement();
        }

        /// <summary>
        /// Liefert das Eltern Element
        /// </summary>
        public Element ParentElement { get; private set; }

        /// <summary>
        /// Liefert den Element Typ
        /// </summary>
        public virtual ElementTypes ElementType
        {
            get;
            protected set;
        }

        /// <summary>
        /// Liefert den Modifizierer
        /// </summary>
        public Modifiers Modifier { get; set; }

        /// <summary>
        /// Gibt das Feld als Virtual markiert werden soll
        /// </summary>
        public bool IsVirtual { get; set; }

        /// <summary>
        /// Liefert den Datentyp
        /// </summary>
        public TypeInfo Type { get; internal set; }

        /// <summary>
        /// Liefert den Elementnamen oder legt ihn fest
        /// </summary>
        public string Elementname { get; set; }

        //public int Position { get; set; }
        //public int Length { get; set; }

        /// <summary>
        /// Liefert den Namespace in dem es enthalten ist
        /// </summary>
        public NamespaceElement Namespace { get; private set; }

        /// <summary>
        /// Liefert den Kompletten Typenamen inklusive Namespace
        /// </summary>
        public string Fullname
        {
            get
            {
                if (Namespace == null)
                    return Elementname;
                else
                    return Namespace.Elementname + "." + Elementname;
            }
        }

        /// <summary>
        /// Gibt das Projekt-Element zurück
        /// </summary>
        /// <returns></returns>
        public ProjectElement GetProjectElement()
        {
            if (ParentElement == null)
                return (ProjectElement)this;

            var element = this.ParentElement;

            while (element.ParentElement != null)
            {
                element = element.ParentElement;
            }

            return (ProjectElement)element;
        }

        /// <summary>
        /// Liefert das Namespace Element zurück, in dem dieses Element enthalten ist
        /// </summary>
        private void GetNamespaceElement()
        {
            var element = this.ParentElement;

            if (element == null)
                return;

            if (element is ProjectElement)
            {
                Namespace = (NamespaceElement)this;
                return;
            }

            while ((element.ParentElement is NamespaceElement))
            {
                element = element.ParentElement;
            }

            Namespace = (NamespaceElement)element;
        }

        /// <summary>
        /// Liefert eine Liste mit Unterelementen
        /// </summary>
        public ElementCollection ChildElements
        {
            get { return _ChildElements; }
        }

        /// <summary>
        ///  Liefert die Textbezeichnung des Elements
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("{0} {1} {2}", Modifier.ToString(), ElementType.ToString(), Elementname); 
        }
    }
}
